#include "File.h"

namespace util {

File::File(std::string fileName) {
	this->fileName = fileName;
	this->file = NULL;
	this->line = 0;
	this->col = 0;
}

File* File::openFileReadOnly() throw (IOException) {
	this->openFile("r");
	this->readLine();
	this->line--;
	return this;
}

File* File::openFileWriteOnly() throw (IOException) {
	this->openFile("w");
	return this;
}

void File::openFile(std::string method) throw (IOException) {
	this->file = fopen(this->fileName.c_str(), method.c_str());
	if (this->file != NULL) {
		this->method = method;
	} else {
		std::string message("Error al abrir el archivo: " + this->fileName);
		throw(IOException(message));
	}
}

File::~File() {
	if (this->file != NULL) {
		fclose(this->file);
	}
}

bool File::isOpen() {
	return (this->file != NULL);
}

std::string File::readLine() throw (IOException) {
	std::string ret = this->currentLine;
	if (std::string("w").compare(this->method) != 0) {
		std::string buf("");
		char c = getc(this->file);
		if (ferror(this->file)) {
			throw(IOException(this->buildErrorMessage()));
		}
		while (c != EOF) {
			if (c != '\n') {
				buf += c;
			} else {
				this->col = 1;
				break;
			}
			c = getc(this->file);
			this->col++;
		}
		this->line++;
		this->currentLine = buf;
		return ret;
	} else {
		throw(IOException("El archivo no esta abierto para lectura."));
	}
}

File* File::appendLine(std::string line) throw (IOException) {
	if (std::string("r").compare(this->method) != 0) {
		int ret = fputs(line.c_str(), this->file);
		if (ret == EOF) {
			std::string message("No se pudo escribir en el archivo: ");
			message.append(this->fileName.c_str());
			throw(IOException(message));
		}
	} else {
		std::string message("El archivo no esta abierto para escritura: ");
		message.append(this->fileName.c_str());
		throw(IOException(message));
	}
	return this;
}

bool File::endOfFile() {
	return ((this->file != NULL) && (feof(this->file) != 0));
}

int File::getCurrentLineNumber() {
	return (this->file != NULL) ? this->line : -1;
}

std::string File::getFileName() {
	return this->fileName;
}

std::string File::buildErrorMessage() {
	std::string message("Error leyendo el archivo: ");
	message.append(this->fileName);
	message.append(" (fila: ");
	char * aux = new char[5];
	sprintf(aux, "%i", line);
	message.append(aux);
	message.append(", columna: ");
	aux[1] = '\0';
	sprintf(aux, "%i", col - 1);
	message.append(aux);
	delete[] aux;
	message.append(")");
	return message;
}
}
